// Copyright 2022 jeff.li. and/or its affiliates.

#include <tbir/ir/adt.h>
#include <tbir/ir/type.h>
#include <tbir/runtime/registry.h>

namespace tbir::ir {

    using namespace ::tbir::runtime;

    TBIR_REGISTER_GLOBAL("ir.Type_GetRuntimeTypeCode").set_body([](PyArgs args) -> RTValue {
        MXCHECK_EQ(args.size(), 1) << "[runtime.RTValue_GetTypeCode] Expect 1 arguments but get "
                                   << args.size();
        int64_t type_code = INT16_MIN;
        Type t = args[0].As<Type>();
        if (IsPrimType(t)) {
            auto node = t.as<PrimTypeNode>();
            switch (node->dtype.code()) {
                case kDLUInt:
                case kDLInt: {
                    type_code = TypeIndex::kRuntimeInteger;
                }
                    break;
                case kDLBfloat:
                case kDLFloat: {
                    type_code = TypeIndex::kRuntimeFloat;
                }
                    break;

                default: {
                    type_code = TypeIndex::kRuntimeOpaqueHandle;
                }
                    break;
            }
        } else if (IsStringType(t)) {
            type_code = TypeIndex::kRuntimeString;
        } else if (IsUnicodeType(t)) {
            type_code = TypeIndex::kRuntimeUnicode;
        } else if (IsListType(t)) {
            type_code = TypeIndex::kRuntimeList;
        } else if (IsDictType(t)) {
            type_code = TypeIndex::kRuntimeDict;
        } else if (IsSetType(t)) {
            type_code = TypeIndex::kRuntimeSet;
        } else if (IsTrieType(t)) {
            type_code = TypeIndex::kRuntimeTrie;
        } else if (IsFileType(t)) {
            type_code = TypeIndex::kRuntimeFile;
        } else if (IsIteratorType(t)) {
            type_code = TypeIndex::kRuntimeIterator;
        } else if (IsUserDataType(t) || t->IsInstance<ClassTypeNode>()) {
            type_code = TypeIndex::kRuntimeUserData;
        }
        return type_code;
    });

}  // namespace tbir::ir
